
#ifndef _PAGING_H
#define _PAGING_H

#include <stdint.h>
#include <stddef.h>

#define PAGING_CACHE_DISABLED          0b00010000
#define PAGING_WRITE_THROUGH           0b00001000
#define PAGING_ACCESS_FROM_ALL         0b00000100
#define PAGING_IS_WRITEABLE            0b00000010
#define PAGING_IS_PRESENT              0b00000001
#define PAGING_TOTAL_ENTRIES_PER_TABLE 1024
#define PAGING_PAGE_SIZE               4096

struct paging_4Gbyte_chunk
{
    uint32_t* directory_entry; 
}
__attribute__((packed));

struct paging_4Gbyte_chunk* paging_new_4Gbyte(uint8_t flags); 
void paging_switch(struct paging_4Gbyte_chunk* directory); 
void enable_paging(); 

uint32_t* paging_4Gbyte_chunk_get_directory(struct paging_4Gbyte_chunk* chunk);


/*
 * Usage of a function: 
 *   void* ptr = kzalloc(4096); 
 *   paging_set(dir, (void*)0x1000,(uint32_t)ptr | PAGING_ACCESS_FROM_ALL | PAGING_IS_PRESENT | PAGING_IS_WRITEABLE); 
 *
 */
int paging_set(uint32_t* directory, void* virtual_address, uint32_t value); 


int paging_is_aligned(void* address); 

void paging_free_4Gbyte(struct paging_4Gbyte_chunk* chunk); 

const int paging_map(
    struct paging_4Gbyte_chunk* directory, 
    void* virt, 
    void* phys,
    const int flags);

const int paging_map_range(
    struct paging_4Gbyte_chunk* directory, 
    void* virt, 
    void* phys,
    const int count, 
    const int flags); 

const int paging_map_to(
    struct paging_4Gbyte_chunk* directory, 
    void* virt, 
    void* phys,
    void* phys_end,
    const int flags);


void* paging_align_address(void* ptr);
const uint32_t paging_get(uint32_t* directory, void* virt); 

#endif